const express = require('express');
const crypto = require('crypto');
const QRCode = require('qrcode');
const cors = require('cors');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const config = require('./config');

const app = express();

// 启用 gzip 压缩
if (config.PERFORMANCE.COMPRESSION) {
    app.use(compression());
}

// 设置并发限制
const limiter = rateLimit({
    windowMs: config.RATE_LIMIT.WINDOW_MS,
    max: config.RATE_LIMIT.MAX_REQUESTS,
    message: {
        code: -1,
        message: '请求过于频繁，请稍后再试'
    }
});
app.use(limiter);

// 基础中间件配置
app.use(express.json());
app.use(cors());

// 工具函数：加密URL
const encryptUrl = (url) => {
    // 生成随机初始化向量
    const iv = crypto.randomBytes(config.CRYPTO.IV_LENGTH);
    
    // 使用 scrypt 生成标准长度的密钥
    const key = crypto.scryptSync(config.CRYPTO.SECRET_KEY, 'salt', 32);
    
    // 创建加密器
    const cipher = crypto.createCipheriv(
        config.CRYPTO.ALGORITHM,
        key,
        iv
    );
    
    // 加密URL
    let encrypted = cipher.update(url, 'utf8');
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    
    // 将IV和加密后的数据组合并使用URL安全的Base64编码
    const combined = Buffer.concat([iv, encrypted]);
    return combined.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '');
};

// 工具函数：解密URL
const decryptUrl = (encryptedData) => {
    try {
        // 还原Base64编码
        const data = encryptedData
            .replace(/-/g, '+')
            .replace(/_/g, '/');
        
        // 解码Base64
        const buffer = Buffer.from(data, 'base64');
        
        // 提取IV和加密数据
        const iv = buffer.slice(0, config.CRYPTO.IV_LENGTH);
        const encrypted = buffer.slice(config.CRYPTO.IV_LENGTH);
        
        // 使用相同的方式生成密钥
        const key = crypto.scryptSync(config.CRYPTO.SECRET_KEY, 'salt', 32);
        
        // 创建解密器
        const decipher = crypto.createDecipheriv(
            config.CRYPTO.ALGORITHM,
            key,
            iv
        );
        
        // 解密数据
        const decrypted = Buffer.concat([
            decipher.update(encrypted),
            decipher.final()
        ]);
        
        return decrypted.toString('utf8');
    } catch (error) {
        throw new Error('解密失败：无效的加密数据');
    }
};

// 工具函数：检测设备类型
const isMobile = (userAgent) => {
    return /mobile|iphone|ipad|android/i.test(userAgent.toLowerCase());
};

// 生成中转链接
app.post(`${config.API_PREFIX}/generate_mid_url`, async (req, res) => {
    try {
        const { url } = req.body;
        
        // 输入验证
        if (!url) {
            return res.status(400).json({
                code: -1,
                message: '请提供有效的URL'
            });
        }
        
        // 加密URL
        const encryptedUrl = encryptUrl(url);
        
        // 直接使用原始URL生成二维码，这样扫描后就能直接访问目标网站
        const qrCode = await QRCode.toDataURL(url);
        
        res.json({
            code: 0,
            url_data: encryptedUrl,
            qr_data: qrCode
        });
    } catch (error) {
        console.error('生成中转链接错误:', error);
        res.status(500).json({
            code: -1,
            message: '服务器内部错误'
        });
    }
});

// 解析目标URL
app.get(`${config.API_PREFIX}/set_target_url`, async (req, res) => {
    try {
        const { url } = req.query;
        const userAgent = req.headers['user-agent'];
        
        // 输入验证
        if (!url) {
            return res.status(400).json({
                code: -1,
                message: '请提供有效的加密URL'
            });
        }
        
        // 解密URL
        const decryptedUrl = decryptUrl(url);
        
        // 根据设备类型返回不同响应
        if (isMobile(userAgent)) {
            // 移动端返回解密后的URL
            res.json({
                code: 0,
                data: decryptedUrl
            });
        } else {
            // 桌面端返回二维码
            const qrCode = await QRCode.toDataURL(decryptedUrl);
            res.json({
                code: 1,
                data: qrCode
            });
        }
    } catch (error) {
        console.error('解析目标URL错误:', error);
        res.status(500).json({
            code: -1,
            message: '服务器内部错误'
        });
    }
});

// 错误处理中间件
app.use((err, req, res, next) => {
    console.error('全局错误处理:', err);
    res.status(500).json({
        code: -1,
        message: '服务器内部错误'
    });
});

// 启动服务器
app.listen(config.PORT, () => {
    console.log(`服务器运行在端口 ${config.PORT}`);
});

module.exports = app;